﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Slf;
using Slf.Factories;

namespace SLF.Test.Factories
{
  [TestClass]
  public class SingleLoggerFactoryTest
  {
    private TestLogger logger;

    [TestInitialize]
    public void Init()
    {
      logger = new TestLogger();
      LoggerService.SetDiagnosticLoggerFactory(new SimpleLoggerFactory(logger));
    }

    [TestCleanup]
    public void Cleanup()
    {
      LoggerService.SetDiagnosticLoggerFactory(null);
    }


    [TestMethod]
    public void Init_ConfiguredForConsoleLogger_CorrectLoggerTypeInstantiated()
    {
      SingleLoggerFactory factory = new SingleLoggerFactory();
      factory.Init("<logger type=\"Slf.ConsoleLogger, SLF\" />");

      Assert.IsInstanceOfType(factory.Logger, typeof(ConsoleLogger));
    }

    [TestMethod]
    public void Init_InvalidXML_LogsError()
    {
      var factory = new SingleLoggerFactory();

      // XML with non-closed element
      factory.Init("<logger type=\"Slf.ConsoleLogger, SLF\" >");

      // check that the initialisation exception was logged
      Assert.AreEqual(1, logger.LoggedItems.Count);
      Assert.AreEqual(LogLevel.Error, logger.LoggedItems[0].LogLevel);
      Assert.IsNotNull(logger.LoggedItems[0].Exception);

      // check that factory is configured with a NullLogger
      Assert.IsInstanceOfType(factory.Logger, typeof(NullLogger));
    }

    [TestMethod]
    public void Init_IncorrectXML_LogsError()
    {
      var factory = new SingleLoggerFactory();

      // XML with non-closed element
      factory.Init("<splodge type=\"Slf.ConsoleLogger, SLF\" />");

      // check that the initialisation exception was logged
      Assert.AreEqual(1, logger.LoggedItems.Count);
      Assert.AreEqual(LogLevel.Error, logger.LoggedItems[0].LogLevel);
      Assert.IsNotNull(logger.LoggedItems[0].Exception);

      // check that factory is configured with a NullLogger
      Assert.IsInstanceOfType(factory.Logger, typeof(NullLogger));
    }

    [TestMethod]
    public void Init_NonExistantType_LogsError()
    {
      var factory = new SingleLoggerFactory();

      // XML with non-existant type
      factory.Init("<logger type=\"foo.bar\" />");

      // check that the initialisation exception was logger
      Assert.AreEqual(1, logger.LoggedItems.Count);
      Assert.AreEqual(LogLevel.Error, logger.LoggedItems[0].LogLevel);      

      // check that factory is configured with a NullLogger
      Assert.IsInstanceOfType(factory.Logger, typeof(NullLogger));
    }

    [TestMethod]
    public void Init_ActivatorUnableToCreatType_LogsError()
    {
      var factory = new SingleLoggerFactory();

      // XML with non-existant type
      factory.Init("<logger type=\"System.String\" />");

      // check that the initialisation exception was logger
      Assert.AreEqual(1, logger.LoggedItems.Count);
      Assert.AreEqual(LogLevel.Error, logger.LoggedItems[0].LogLevel);

      // check that factory is configured with a NullLogger
      Assert.IsInstanceOfType(factory.Logger, typeof(NullLogger));
    }

    [TestMethod]
    public void Init_TypeIsNotILogger_LogsError()
    {
      var factory = new SingleLoggerFactory();

      // XML with non-existant type
      factory.Init("<logger type=\"Slf.Factories.SingleLoggerFactory, SLF\" />");

      // check that the initialisation exception was logger
      Assert.AreEqual(1, logger.LoggedItems.Count);
      Assert.AreEqual(LogLevel.Error, logger.LoggedItems[0].LogLevel);

      // check that factory is configured with a NullLogger
      Assert.IsInstanceOfType(factory.Logger, typeof(NullLogger));
    }
  }
}
